package com.qcq.wecheck.service.impl;

import cn.afterturn.easypoi.entity.vo.MapExcelConstants;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.view.PoiBaseView;
import com.qcq.wecheck.dto.AttendanceCountDto;
import com.qcq.wecheck.entity.Attendance;
import com.qcq.wecheck.entity.Schedule;
import com.qcq.wecheck.entity.User;
import com.qcq.wecheck.service.AttendanceService;
import com.qcq.wecheck.service.ExportService;
import com.qcq.wecheck.service.ScheduleService;
import com.qcq.wecheck.service.UserService;
import com.qcq.wecheck.util.PredicateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 *
 * </p>
 *
 * @author O
 * @version 1.0
 * @since 2018/10/16
 */
@Service
@Slf4j
public class ExportServiceImpl implements ExportService {
	private static final String NAME = "name";
	private static final String NICKNAME = "nickname";
	private static final String TEL = "tel";
	private static final String REMARK = "remark";
	private static final String TOTAL = "total";
	private static final String FINISH = "finish";
	private static final String UNFINISHED = "unfinished";
	private static final String UNCHECK_COUNT = "uncheckCount";
	@Resource
	private UserService userService;
	@Resource
	private ScheduleService scheduleService;
	@Resource
	private AttendanceService attendanceService;

	@Override
	public void exportSimple(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response, Schedule schedule) {
		int count = (int) ChronoUnit.DAYS.between(schedule.getStartDate(), schedule.getEndDate()) + 1;
		User user = userService.selectById(schedule.getCreatorId());
		if (user == null) {
			log.error("user is null ! schedule: {}" + schedule);
			return;
		}
		String fileName = user.getName() + "的考勤表";
		List<ExcelExportEntity> exportEntities = createEntities(schedule, user, count);

		List<Map<String, Object>> list = addMsg(schedule, count);

		ExportParams params = new ExportParams(schedule.getTitle(), "报表统计", ExcelType.HSSF);
		modelMap.put(MapExcelConstants.MAP_LIST, list);
		modelMap.put(MapExcelConstants.ENTITY_LIST, exportEntities);
		modelMap.put(MapExcelConstants.PARAMS, params);
		modelMap.put(MapExcelConstants.FILE_NAME, fileName);
		PoiBaseView.render(modelMap, request, response, MapExcelConstants.EASYPOI_MAP_EXCEL_VIEW);
	}

	/**
	 * 创建列
	 *
	 * @return entityList
	 */
	private List<ExcelExportEntity> createEntities(Schedule schedule, User user, int count) {
		List<ExcelExportEntity> exportEntities = new ArrayList<>();
		//添加姓名列
		exportEntities.add(new ExcelExportEntity("姓名", NAME));

		//添加昵称列
		exportEntities.add(new ExcelExportEntity("微信昵称", NICKNAME));

		//添加电话号码列
		exportEntities.add(new ExcelExportEntity("联系电话", TEL));

		//备注列
		exportEntities.add(new ExcelExportEntity("备注", REMARK));


		//总天数
		exportEntities.add(new ExcelExportEntity("总计天数", TOTAL));

		//全勤天数
		exportEntities.add(new ExcelExportEntity("全勤天数", FINISH));

		//未完成天数
		exportEntities.add(new ExcelExportEntity("缺勤天数", UNFINISHED));

		//未考勤天数
		exportEntities.add(new ExcelExportEntity("未进行天数", UNCHECK_COUNT));

		//添加日期列
		List<ExcelExportEntity> exportEntityList = Stream.iterate(schedule.getStartDate(), localDate -> localDate.plusDays(1))
				.map(localDate -> {
					String date = localDate.format(DateTimeFormatter.ISO_DATE);
					ExcelExportEntity entity = new ExcelExportEntity(date, date);
					List<ExcelExportEntity> list = new ArrayList<>();
					list.add(new ExcelExportEntity("完成情况", "status"));
					for (int i = 0; i < schedule.getCheckCount(); i++) {
						list.add(new ExcelExportEntity("第" + (i + 1) + "次", String.valueOf(i)));

					}

					entity.setList(list);

					return entity;
				})
				.limit(count)
				.collect(Collectors.toList());
		exportEntities.addAll(exportEntityList);

		return exportEntities;
	}

	/**
	 * 添加数据
	 *
	 * @return list
	 */
	private List<Map<String, Object>> addMsg(Schedule schedule, int count) {
		int requiredCount = schedule.getCheckCount();
		List<User> users = scheduleService.getMember(schedule.getId(), null);
		List<Map<String, Object>> list = new ArrayList<>();
		for (User user : users) {
			List<AttendanceCountDto> countDtos = attendanceService.getAttendanceCount(user.getOpenId(),
					schedule.getId(),
					schedule.getStartDate().format(DateTimeFormatter.ISO_DATE),
					schedule.getEndDate().format(DateTimeFormatter.ISO_DATE));
			//该map代表所有一行的数据
			Map<String, Object> map = new HashMap<>();
			//名字列
			map.put(NAME, user.getName());
			//备注列
			map.put(REMARK, user.getRemark());

			//日期列(嵌套)
			Map<String, Object> dateMap = countDtos.parallelStream()
					.filter(PredicateUtils::isLegalDateAttendanceCountVo)
					.collect(Collectors.toMap(
							//key
							dto -> dto.getDate().format(DateTimeFormatter.ISO_DATE),
							//value
							dto -> {
								List<Attendance> attendances = attendanceService.getByDate(schedule.getCreatorId(), schedule.getId(), dto.getDate().format(DateTimeFormatter.ISO_DATE));

								//initialCapacity: status+考勤次数
								Map<String, Object> tempMap = new HashMap<>(count + 1);
								String status = dto.getCount() < requiredCount ? "×" : "√";
								tempMap.put("status", status);
								//添加考勤记录时间
								if (attendances != null) {
									for (int i = 0; i < attendances.size(); i++) {
										tempMap.put(String.valueOf(i), attendances.get(i).getCheckTime().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
									}
								}


								List<Map<String, Object>> tempList = new ArrayList<>();
								tempList.add(tempMap);

								return tempList;
							}));


			map.putAll(dateMap);


			/*
			 * 关于日期的正确赋值方式
			 * Map<String, Object> tempMap = new HashMap<>()
			 * tempMap.put("status", "√")
			 * tempMap.put("1", LocalTime.now().format(DateTimeFormatter.ISO_TIME))
			 * tempMap.put("2", LocalTime.now().format(DateTimeFormatter.ISO_TIME))
			 * tempMap.put("3", LocalTime.now().format(DateTimeFormatter.ISO_TIME))
			 *
			 * List<Map<String, Object>> tempList = new ArrayList<>()
			 * tempList.add(tempMap)
			 * map.put("2018-10-23",tempList)
			 */

			long finish = countDtos.stream()
					.filter(dto -> PredicateUtils.isFinishedAttendanceCountVo(dto, requiredCount))
					.count();

			long legalCount = countDtos.stream()
					.filter(PredicateUtils::isLegalDateAttendanceCountVo)
					.count();

			//总数列
			map.put(TOTAL, count);
			map.put(FINISH, finish);
			map.put(UNFINISHED, legalCount - finish);
			map.put(NICKNAME, user.getNickname());
			map.put(UNCHECK_COUNT, count - legalCount);

			//添加一整行的数据
			list.add(map);
		}
		return list;
	}
}

